<template>
    <div class="validate-input-container pb-3">
        <input v-if="tag !== 'textarea'" class="form-control" :class="{'is-invalid': inputRef.error}" :value="inputRef.val" 
        @blur="validateInput" 
        @input="updateValue"
        v-bind="$attrs" />
        <textarea v-else class="form-control" :class="{'is-invalid': inputRef.error}" :value="inputRef.val" 
        @blur="validateInput" 
        @input="updateValue"
        v-bind="$attrs"></textarea>
        <span class="invalid-feedback" v-if="inputRef.error">{{ inputRef.message }}</span>
    </div>
</template>

<script setup lang="ts">
import { PropType, reactive, onMounted } from 'vue'
import emitter from '../hooks/useEmitter'

const emailReg = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/

interface RuleProp {
    type: 'required' | 'email' | 'range' | 'custom'
    message: string
    validator?: (val: string) => boolean
}
export type RulesProp = RuleProp[]
export type TagType = 'input' | 'textarea'
const props = defineProps({
    rules: Array as PropType<RulesProp>,
    modelValue: String,
    tag: {
        type: String as PropType<TagType>,
        default: 'input'
    }
})
const inputRef = reactive({
  val: props.modelValue || '',
  error: false,
  message: ''
})
const validateInput = () => {
    if (props.rules) {
        const allPassed = props.rules.every(rule => {
            let passed = true
            inputRef.message = rule.message
            switch(rule.type) {
                case 'required':
                passed = inputRef.val.trim() !== ''
                break
                case 'email':
                passed = emailReg.test(inputRef.val)
                break
                case 'range':
                passed = inputRef.val.length >= 6 && inputRef.val.length <= 12
                break
                case 'custom':
                passed = rule.validator ? rule.validator(inputRef.val) : true
                break
            }
            return passed
        })
        inputRef.error = !allPassed
        return allPassed
    }
    return true
}
const emit = defineEmits()
const updateValue = (e: KeyboardEvent) => {
    const targetValue = (e.target as HTMLInputElement).value
    inputRef.val = targetValue
    emit('update:modelValue', targetValue)
}

onMounted(() => {
    emitter.emit('form-item-created', validateInput)
})
</script>